using MediatR;
using TerritoryGame.Application.Commands;
using TerritoryGame.Domain.Entities;
using TerritoryGame.Domain.Repositories;
using TerritoryGame.Domain.ValueObjects;

namespace TerritoryGame.Application.Handlers.CommandHandlers;

public class JoinRoomCommandHandler : IRequestHandler<JoinRoomCommand, JoinRoomResult>
{
    private readonly IGameRoomRepository _gameRoomRepository;
    private readonly IGameRepository _gameRepository;

    public JoinRoomCommandHandler(IGameRoomRepository gameRoomRepository, IGameRepository gameRepository)
    {
        _gameRoomRepository = gameRoomRepository;
        _gameRepository = gameRepository;
    }

    public async Task<JoinRoomResult> Handle(JoinRoomCommand request, CancellationToken cancellationToken)
    {
        try
        {
            GameRoom? room;
            
            // 如果提供了房间代码，通过代码查找房间
            if (!string.IsNullOrEmpty(request.RoomCode))
            {
                room = await _gameRoomRepository.GetByCodeAsync(request.RoomCode);
            }
            else if (!string.IsNullOrEmpty(request.RoomId))
            {
                // 尝试解析为Guid，如果失败则作为房间代码处理
                if (Guid.TryParse(request.RoomId, out var roomId))
                {
                    room = await _gameRoomRepository.GetByIdAsync(roomId);
                }
                else
                {
                    room = await _gameRoomRepository.GetByCodeAsync(request.RoomId);
                }
            }
            else
            {
                return new JoinRoomResult
                {
                    Success = false,
                    ErrorMessage = "Room ID or Room Code is required"
                };
            }
            if (room == null)
            {
                return new JoinRoomResult
                {
                    Success = false,
                    ErrorMessage = "Room not found"
                };
            }

            if (room.Status != GameStatus.Waiting)
            {
                return new JoinRoomResult
                {
                    Success = false,
                    ErrorMessage = "Room is not in waiting status"
                };
            }

            if (room.Players.Count >= room.MaxPlayers)
            {
                return new JoinRoomResult
                {
                    Success = false,
                    ErrorMessage = "Room is full"
                };
            }

            // 检查密码
            if (!string.IsNullOrEmpty(room.Password))
            {
                if (string.IsNullOrEmpty(request.Password))
                {
                    return new JoinRoomResult
                    {
                        Success = false,
                        ErrorMessage = "Password required",
                        ErrorCode = "PASSWORD_REQUIRED"
                    };
                }
                
                if (room.Password != request.Password)
                {
                    return new JoinRoomResult
                    {
                        Success = false,
                        ErrorMessage = "Invalid password",
                        ErrorCode = "INVALID_PASSWORD"
                    };
                }
            }

            // Check if player already exists in the room
            var existingPlayer = room.Players.FirstOrDefault(p => p.Id == request.PlayerId);
            if (existingPlayer != null)
            {
                // 玩家已存在，返回成功（重新加入）
                return new JoinRoomResult
                {
                    RoomId = room.Id,
                    PlayerId = existingPlayer.Id,
                    PlayerColor = existingPlayer.Color,
                    RoomName = room.Name,
                    Success = true
                };
            }

            // Create new player with provided ID
            var random = new Random();
            var usedColors = room.Players.Select(p => p.Color.Value).ToHashSet();
            var candidateColors = PlayerColor.AvailableColors.Where(c => !usedColors.Contains(c.Value)).ToArray();
            var randomColor = (candidateColors.Length > 0
                ? candidateColors[random.Next(candidateColors.Length)]
                : PlayerColor.AvailableColors[random.Next(PlayerColor.AvailableColors.Length)]);
            var player = new Player(
                request.PlayerId,
                request.PlayerNickName,
                randomColor
            );

            // Add player to room (pass the password since we already validated it)
            var addPlayerResult = await _gameRoomRepository.AddPlayerToRoomAsync(room.Id, player, request.Password);
            if (!addPlayerResult)
            {
                return new JoinRoomResult
                {
                    Success = false,
                    ErrorMessage = "Failed to add player to room"
                };
            }

            return new JoinRoomResult
            {
                RoomId = room.Id,
                PlayerId = player.Id,
                PlayerColor = player.Color,
                RoomName = room.Name,
                Success = true
            };
        }
        catch (Exception ex)
        {
            return new JoinRoomResult
            {
                Success = false,
                ErrorMessage = ex.Message
            };
        }
    }
}
